home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / rpc / rpcInit.c < prev    next >
C/C++ Source or Header  |  1992-12-18  |  16KB  |  508 lines

  1. /*
  2.  * rpcInit.c --
  3.  *
  4.  *    Initialize the data structures needed by the RPC system.
  5.  *
  6.  * Copyright (C) 1985 Regents of the University of California
  7.  * All rights reserved.
  8.  */
  9.  
  10. #ifndef lint
  11. static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/rpc/rpcInit.c,v 9.14 92/04/14 17:04:27 jhh Exp $ SPRITE (Berkeley)";
  12. #endif /* not lint */
  13.  
  14. #include <sprite.h>
  15. #include <stdio.h>
  16. #include <rpc.h>
  17. #include <rpcInt.h>
  18. #include <rpcClient.h>
  19. #include <rpcServer.h>
  20. #include <rpcTrace.h>
  21. #include <vm.h>
  22. #include <timer.h>
  23. #include <net.h>
  24.  
  25. /*
  26.  * These are the rpc version numbers, both in native format and in
  27.  * byte-swapped format. 
  28.  */
  29.  
  30. int    rpc_NativeVersion = RPC_NATIVE_VERSION;
  31. int    rpc_SwappedVersion = RPC_SWAPPED_VERSION;
  32.  
  33. /*
  34.  * Constant parameters for the protocol.  The RpcConst structure keeps
  35.  * the complete set of constants.  Two sets of constants are defined,
  36.  * one that is appropriate for a local ethernet, one that has longer
  37.  * timeouts and is better for talking across gateways.
  38.  */
  39. RpcConst rpcEtherConst;
  40. RpcConst rpcInetConst;
  41.  
  42. void RpcBufferInit();
  43.  
  44.  
  45. /*
  46.  *----------------------------------------------------------------------
  47.  *
  48.  * Rpc_Init --
  49.  *
  50.  *      Allocate and set up the tables used by the RPC system.  This
  51.  *      should be called after virtual memory allocation can be done and
  52.  *      before any RPCs are attempted.  This allocates the Client Channel
  53.  *    data structures and some stuff for the Rpc Servers' state.  The
  54.  *    number of client channels is fixed by rpcNumChannels, but the
  55.  *    number of RPC server processes can grow via the Rpc_Deamon process.
  56.  *
  57.  * Results:
  58.  *    None.
  59.  *
  60.  * Side effects:
  61.  *    Allocate space for tables, and set the initial state for the
  62.  *    client channels and the servers.
  63.  *
  64.  *----------------------------------------------------------------------
  65.  */
  66. void
  67. Rpc_Init()
  68. {
  69.     int i;
  70.     register int frag;
  71.     extern void    RpcInitServerTraces();
  72.  
  73.     /*
  74.      * Initialize sets of time parameters.  These structures are used in
  75.      * the RpcDoCall code.  This is much too hard coded, and someone
  76.      * should figure out how to dynamically determine these parameters.
  77.      *
  78.      * Ethernet - retry after 0.1 seconds, .5 seconds if fragmenting.
  79.      *    Double this until the retry interval is 1 second.
  80.      *    Retry at most 8 times, for a total timeout period of
  81.      *        .1 + .2 + .4 + .8 + 1.0 + 1.0 + 1.0 + 1.0 = 5.5
  82.      *        .5 + 1.0 + 1.0 + 1.0 + 1.0 + 1.0 + 1.0 + 1.0 = 7.5 (frag)
  83.      *    If we are recieving acks, then back off and probe every 5 seconds.
  84.      *    If we get acked 10 times then give a warning.
  85.      */
  86.     rpcEtherConst.retryMsec = 100;
  87.     rpcEtherConst.retryWait = 100 * timer_IntOneMillisecond;
  88.     rpcEtherConst.fragRetryMsec = 500;
  89.     rpcEtherConst.fragRetryWait = 500 * timer_IntOneMillisecond;
  90.     rpcEtherConst.maxAckMsec = 5000;
  91.     rpcEtherConst.maxAckWait = 5000 * timer_IntOneMillisecond;
  92.     rpcEtherConst.maxTimeoutMsec = 1000;
  93.     rpcEtherConst.maxTimeoutWait = 1000 * timer_IntOneMillisecond;
  94.     rpcEtherConst.maxTries = 8;
  95.     rpcEtherConst.maxAcks = 10;
  96.     /*
  97.      * Internet (IP) - retry after 0.5 seconds, 1.0 if fragmenting.
  98.      *    Double this until the retry interval is 4 seconds.
  99.      *    Retry at most 8 times, for a total timeout period of
  100.      *        .5 + 1.0 + 2.0 + 4.0 + 4.0 + 4.0 + 4.0 + 4.0 = 23.5
  101.      *        1.0 + 2.0 + 4.0 + 4.0 + 4.0 + 4.0 + 4.0 + 4.0 = 27.0 (frag)
  102.      *    If we are recieving acks, then back off and probe every 5 seconds.
  103.      *    If we get acked 10 times then give a warning.
  104.      */
  105.     rpcInetConst.retryMsec = 500;
  106.     rpcInetConst.retryWait = 500 * timer_IntOneMillisecond;
  107.     rpcInetConst.fragRetryMsec = 1000;
  108.     rpcInetConst.fragRetryWait = 1000 * timer_IntOneMillisecond;
  109.     rpcInetConst.maxAckMsec = 5000;
  110.     rpcInetConst.maxAckWait = 5000 * timer_IntOneMillisecond;
  111.     rpcInetConst.maxTimeoutMsec = 4000;
  112.     rpcInetConst.maxTimeoutWait = 4000 * timer_IntOneMillisecond;
  113.     rpcInetConst.maxTries = 8;
  114.     rpcInetConst.maxAcks = 10;
  115.  
  116.     /*
  117.      * TRACE and HISTOGRAM initialization.
  118.      */
  119.     Trace_Init(rpcTraceHdrPtr, RPC_TRACE_LEN, sizeof(RpcHdr), 0);
  120.  
  121.     rpcServiceTime[0] = (Rpc_Histogram *)NIL;
  122.     rpcCallTime[0] = (Rpc_Histogram *)NIL;
  123.     for (i=1 ; i<=RPC_LAST_COMMAND ; i++) {
  124.     rpcServiceTime[i] = Rpc_HistInit(RPC_NUM_HIST_BUCKETS, 1024);
  125.     rpcCallTime[i] = Rpc_HistInit(RPC_NUM_HIST_BUCKETS, 1024);
  126.     }
  127.  
  128.     /*
  129.      * Set our preferred inter-fragment delay based on machine type.
  130.      * This is a microsecond value.  Our output rate starts the same
  131.      * as the input rate, although MyDelay could increase if a machine
  132.      * senses that it is overloaded.
  133.      */
  134.  
  135.     RpcGetMachineDelay(&rpcMyDelay, &rpcOutputRate);
  136.  
  137.     /*
  138.      * The client channel table is kept as a pointer to an array of pointers
  139.      * to client channels.  First allocate the table of pointers and then
  140.      * allocate storage for each channel.
  141.      */
  142.     rpcChannelPtrPtr = (RpcClientChannel **)
  143.         Vm_RawAlloc(rpcNumChannels * sizeof(RpcClientChannel *));
  144.  
  145.     /*
  146.      * Query the net module of the maximum size protocol header buffer 
  147.      * needed.
  148.      */
  149.     for (i=0 ; i<rpcNumChannels ; i++) {
  150.     register RpcClientChannel *chanPtr;
  151.  
  152.     chanPtr = (RpcClientChannel *)Vm_RawAlloc(sizeof(RpcClientChannel));
  153.     rpcChannelPtrPtr[i] = chanPtr;
  154.  
  155.     chanPtr->state = CHAN_FREE;
  156.     chanPtr->index = i;
  157.     chanPtr->serverID = -1;
  158.     Sync_SemInitDynamic(&chanPtr->mutex,"Rpc:RpcClientChannel.mutex");
  159.     Sync_SemRegister(&chanPtr->mutex);
  160.     chanPtr->waitCondition.waiting = FALSE;
  161.  
  162.     /*
  163.      * Set up header storage and the scatter/gather sets used to
  164.      * refer to a whole message.  This is done for each type
  165.      * of packet (request, reply ack), plus an array of these
  166.      * things used for fragmenting our request.
  167.      */
  168.     RpcBufferInit((RpcHdr *) &chanPtr->requestRpcHdr, &chanPtr->request,
  169.             chanPtr->index, -1);
  170.     RpcBufferInit(&chanPtr->replyRpcHdr, &chanPtr->reply,
  171.             chanPtr->index, -1);
  172.     RpcBufferInit(&chanPtr->ackHdr, &chanPtr->ack,
  173.             chanPtr->index, -1);
  174.  
  175.     for (frag=0 ; frag < RPC_MAX_NUM_FRAGS ; frag++) {
  176.         RpcBufferInit(&chanPtr->fragRpcHdr[frag], &chanPtr->fragment[frag],
  177.                 chanPtr->index, -1);
  178.     }
  179.  
  180.     }
  181.     /*
  182.      * Initialize server nack info.
  183.      */
  184.     Sync_SemInitDynamic(&rpcNack.mutex,"Rpc:RpcNackData.mutex");
  185.     Sync_SemRegister(&rpcNack.mutex);
  186.     /*
  187.      * Set nack buffers to NIL until allocated when rpc system turned on.
  188.      */
  189.     rpcNack.numFree = 0;
  190.     rpcNack.rpcHdrArray = (RpcHdr *) NIL;
  191.     rpcNack.hdrState = (int *) NIL;
  192.     rpcNack.bufferSet = (RpcBufferSet *) NIL;
  193.  
  194.     /*
  195.      * Initialize client's table on whether servers are sending negative
  196.      * acknowledgements or not (if channel ramping-down is used).
  197.      */
  198.     RpcInitServerChannelState();
  199.  
  200.     /*
  201.      * Initialize neg-ack back-off constants on clients.
  202.      */
  203.     rpcNackRetryWait = 2 * timer_IntOneSecond;
  204.     rpcMaxNackWait = 15 * timer_IntOneSecond;
  205.  
  206.     /*
  207.      * Initialize the servers' state table.  Most slots are left
  208.      * uninitialized.  They get filled in by Rpc_Deamon when it creates
  209.      * new server processes.  After creation, a server process
  210.      * claims a table entry with RpcServerInstall.
  211.      */
  212.     rpcServerPtrPtr = (RpcServerState **)
  213.         Vm_RawAlloc(rpcAbsoluteMaxServers * sizeof(RpcServerState *));
  214.     for (i=0 ; i<rpcMaxServers ; i++) {
  215.     rpcServerPtrPtr[i] = (RpcServerState *)NIL;
  216.     }
  217.  
  218.     /*
  219.      * Ask the net module to set up our Sprite ID.  It uses either
  220.      * existing (compiled in) addresses or Reverse ARP.  If we can't
  221.      * figure out our ID we use zero and rely on the RPC server to
  222.      * propogate our Sprite ID back in the first RPC reply message.
  223.      * We try all the interfaces until we get one that works.
  224.      */
  225.     for (i = 0; ; i++) {
  226.     Net_Interface    *interPtr;
  227.     interPtr = Net_NextInterface(TRUE, &i);
  228.     if (interPtr == (Net_Interface *) NIL) {
  229.         break;
  230.     }
  231.     rpc_SpriteID = Net_AddrToID(&interPtr->netAddress[NET_PROTO_RAW]);
  232.     if (rpc_SpriteID > 0) {
  233.         break;
  234.     }
  235.     }
  236.     if (rpc_SpriteID < 0) {
  237.     rpc_SpriteID = 0;
  238.     }
  239.  
  240.     RpcInitServerTraces();
  241.  
  242.     return;
  243. }
  244.  
  245. /*
  246.  *----------------------------------------------------------------------
  247.  *
  248.  * RpcBufferInit --
  249.  *
  250.  *    Initialize a packet buffer for one of the various packets sent
  251.  *    via an RPC channel.  They all share the same packet format and
  252.  *    buffering system, and this call is used to initialize it.
  253.  *
  254.  * Results:
  255.  *    None.
  256.  *
  257.  * Side effects:
  258.  *    Allocate memory with Vm_RawAlloc.  Give initial values to
  259.  *    the fields of the RPC header that never change.  These are:
  260.  *    version        # byte ordering version.
  261.  *    channel        # channel port number.
  262.  *    delay        # interfragment delay.
  263.  *    paramSize 0    # size of the parameter area of the message.
  264.  *    dataSize 0    # size of the data area of the message.
  265.  *    numFrags 0    # >0 if fragmented
  266.  *    fragMask 0    # fragmentID
  267.  *
  268.  *----------------------------------------------------------------------
  269.  */
  270. void
  271. RpcBufferInit(rpcHdrPtr, bufferSetPtr, channel, serverHint)
  272.     RpcHdr *rpcHdrPtr;        /* Storage for packet header */
  273.     RpcBufferSet *bufferSetPtr;    /* Scatter/gather vector for whole message */
  274.     int channel;        /* chanPtr->index */
  275.     int serverHint;        /* srvPtr->index */
  276. {
  277.     int maxHdrSize = NET_MAX_HEADER_SIZE;
  278.  
  279.     bufferSetPtr->protoHdrBuffer.length = maxHdrSize;
  280.     bufferSetPtr->protoHdrBuffer.bufAddr = Vm_RawAlloc(maxHdrSize);
  281.     bufferSetPtr->protoHdrBuffer.mutexPtr = (Sync_Semaphore *)NIL;
  282.  
  283.     bufferSetPtr->rpcHdrBuffer.length = sizeof(RpcHdr);
  284.     bufferSetPtr->rpcHdrBuffer.bufAddr = (Address)rpcHdrPtr;
  285.     bufferSetPtr->rpcHdrBuffer.mutexPtr = (Sync_Semaphore *)NIL;
  286.  
  287.     bufferSetPtr->paramBuffer.length = 0;
  288.     bufferSetPtr->paramBuffer.bufAddr = (Address)NIL;
  289.     bufferSetPtr->paramBuffer.mutexPtr = (Sync_Semaphore *)NIL;
  290.  
  291.     bufferSetPtr->dataBuffer.length = 0;
  292.     bufferSetPtr->dataBuffer.bufAddr = (Address)NIL;
  293.     bufferSetPtr->dataBuffer.mutexPtr = (Sync_Semaphore *)NIL;
  294.     /*
  295.      * Set up RPC header fields that don't change.
  296.      */
  297.     rpcHdrPtr->version = rpc_NativeVersion;
  298.     rpcHdrPtr->delay = rpcMyDelay;
  299.  
  300.     rpcHdrPtr->clientID = rpc_SpriteID;
  301.     rpcHdrPtr->channel = channel;
  302.     rpcHdrPtr->serverID = rpc_SpriteID;
  303.     rpcHdrPtr->serverHint = serverHint;
  304.     /*
  305.      * And some that might not have to change.
  306.      */
  307.     rpcHdrPtr->numFrags = 0;
  308.     rpcHdrPtr->fragMask = 0;
  309.     rpcHdrPtr->paramSize = 0;
  310.     rpcHdrPtr->dataSize = 0;
  311. }
  312.  
  313. /*
  314.  *----------------------------------------------------------------------
  315.  *
  316.  * RpcInitServerState --
  317.  *
  318.  *    Initialize a server state table entry.  This is called before
  319.  *    a server process is created to set up its state.  The state is
  320.  *    used as the primary communication mechanism between the server
  321.  *    process and the rest of the world.
  322.  *
  323.  * Results:
  324.  *    A pointer to an initialized server state table entry.  This
  325.  *    value needs to be saved in a table somewhere by the caller.
  326.  *
  327.  * Side effects:
  328.  *    Allocate memory with Vm_RawAlloc.  Give initial values to
  329.  *    all the elements of the table entry.  The "state" field of
  330.  *    the table is set to SRV_NOTREADY and a server process has
  331.  *    to claim the table entry with RpcServerInstall.
  332.  *
  333.  *----------------------------------------------------------------------
  334.  */
  335. RpcServerState *
  336. RpcInitServerState(index)
  337.     int index;        /* Caller's index of returned info.  This is saved
  338.              * in the table and used as a hint to clients */
  339. {
  340.     register RpcServerState *srvPtr;    /* Server state that is initialized */
  341.     register int frag;            /* Index into array of headers used
  342.                      * for fragmenting */
  343.     static Sync_Semaphore mutexInit =
  344.     Sync_SemInitStatic("RpcServerState->mutex");
  345.  
  346.     Sync_SemRegister(&mutexInit);
  347.  
  348.     srvPtr = (RpcServerState *)Vm_RawAlloc(sizeof(RpcServerState));
  349.  
  350.     srvPtr->state = SRV_NOTREADY;
  351.     srvPtr->ID = 0;
  352.     srvPtr->freeReplyProc = (int (*)())NIL;
  353.     srvPtr->freeReplyData = (ClientData)NIL;
  354.     srvPtr->index = index;
  355.     srvPtr->clientID = -1;
  356.     srvPtr->channel = -1;
  357.     srvPtr->mutex = mutexInit;
  358.     srvPtr->waitCondition.waiting = FALSE;
  359.  
  360.     /*
  361.      * Set up the buffer address for the RPC header of replies
  362.      * and acks to point to the headers kept here in the server's state.
  363.      */
  364.     RpcBufferInit(&srvPtr->replyRpcHdr, &srvPtr->reply, -1, srvPtr->index);
  365.     RpcBufferInit(&srvPtr->ackRpcHdr, &srvPtr->ack, -1, srvPtr->index);
  366.     for (frag=0 ; frag < RPC_MAX_NUM_FRAGS ; frag++) {
  367.     RpcBufferInit(&srvPtr->fragRpcHdr[frag], &srvPtr->fragment[frag],
  368.             -1, srvPtr->index);
  369.     }
  370.     /*
  371.      * Set up the scatter vector for input requests to the server.
  372.      * Allocate buffer space for the largest possible request.
  373.      */
  374.     RpcBufferInit(&srvPtr->requestRpcHdr, &srvPtr->request, -1, srvPtr->index);
  375.     srvPtr->request.paramBuffer.bufAddr = Vm_RawAlloc(RPC_MAX_PARAMSIZE);
  376.     srvPtr->request.paramBuffer.length = RPC_MAX_PARAMSIZE;
  377.  
  378.     srvPtr->request.dataBuffer.bufAddr = Vm_RawAlloc(RPC_MAX_DATASIZE);
  379.     srvPtr->request.dataBuffer.length = RPC_MAX_DATASIZE;
  380.  
  381.     /*
  382.      * Initialize temporaries.
  383.      */
  384.     srvPtr->actualParamSize = 0;
  385.     srvPtr->actualDataSize = 0;
  386.  
  387.     return(srvPtr);
  388. }
  389.  
  390. /*
  391.  *----------------------------------------------------------------------
  392.  *
  393.  * Rpc_Start --
  394.  *
  395.  *      Conduct the preliminary RPC's neccesary to start up the client
  396.  *      side of the RPC system.  A Get Time RPC is done to initialize the
  397.  *      boot time stamp.
  398.  *
  399.  * Results:
  400.  *    None.
  401.  *
  402.  * Side effects:
  403.  *    Do a Get Time RPC to initialize rpcBootID;
  404.  *
  405.  *----------------------------------------------------------------------
  406.  */
  407. void
  408. Rpc_Start()
  409. {
  410.     Time     bootTime;    /* Time returned from the default server */
  411.     int     tzMinutes;    /* Minutes west of Greenwich */
  412.     int     tzDST;        /* Daylight savings flag */
  413.     ReturnStatus status;    /* Status code from the RPC */
  414.     char     dateString[40];/* To hold a printable version of the time */
  415.     int     seconds;
  416.     int     spriteID;
  417.     Net_Route        *routePtr;
  418.     Sync_Semaphore    tmpMutex;
  419.     int            i;
  420.  
  421.     /*
  422.      * Do a Sprite reverse Arp to discover our Sprite ID.  If it's still
  423.      * zero after this that inhibits the RPC system.  In that case we'd
  424.      * better be a diskfull machine so we find out our SpriteID by
  425.      * the user program that installs routes.  See Net_InstallRoute.
  426.      *
  427.      * We do a reverse arp on all the broadcast routes until one
  428.      * works.
  429.      */
  430.     spriteID = -1;
  431.     i = 0;
  432.     Sync_SemInitDynamic(&tmpMutex, "Rpc_Start:tmpMutex");
  433.     while (1) {
  434.     routePtr = Net_IDToRoute(NET_BROADCAST_HOSTID, i, FALSE, 
  435.             (Sync_Semaphore *) NIL, 0);
  436.     if (routePtr == (Net_Route *) NIL) {
  437.         break;
  438.     }
  439.     MASTER_LOCK(&tmpMutex);
  440.     spriteID = Net_RevArp(routePtr, NET_PROTO_RAW,  
  441.             (Net_Address *) NIL, &tmpMutex); 
  442.     MASTER_UNLOCK(&tmpMutex);
  443.     Net_ReleaseRoute(routePtr);
  444.     if (spriteID > 0) {
  445.         rpc_SpriteID = spriteID;
  446.         printf("Reverse Arp, setting Sprite ID to %d\n", spriteID);
  447.         break;
  448.     }
  449.     i++;
  450.     }
  451.  
  452.     Rpc_StampTest();
  453.  
  454.     status = Rpc_GetTime(RPC_BROADCAST_SERVER_ID, &bootTime, &tzMinutes,
  455.                          &tzDST);
  456.     if (status != SUCCESS) {
  457.     Timer_Ticks ticks;
  458.  
  459.     printf("Rpc_Start: error (%x) from Get Time RPC\n", status);
  460.     Timer_GetCurrentTicks(&ticks);
  461.     Timer_TicksToTime(ticks, &bootTime);
  462.     } else {
  463.     Timer_SetTimeOfDay(bootTime, tzMinutes, tzDST);
  464.     }
  465.     rpcBootID = bootTime.seconds;
  466.  
  467.     /*
  468.      * Convert from Greenwich Standard minutes to local minutes
  469.      * and print the time on the console.
  470.      */
  471.     seconds = bootTime.seconds + tzMinutes * 60;
  472.     Time_ToAscii(seconds, FALSE, dateString);
  473.     printf("%s\n", dateString);
  474. }
  475.  
  476. /*
  477.  *----------------------------------------------------------------------
  478.  *
  479.  * Rpc_MaxSizes --
  480.  *
  481.  *      This function returns the maximum amount of data that can be sent
  482.  *      in one RPC.  A remote procedure has its inputs and outputs packed
  483.  *      into two buffers called the "data area" and the "parameter area".
  484.  *      Two values are returned, the maximums for the parameter and data
  485.  *      areas.
  486.  *
  487.  * Results:
  488.  *    The first parameter gets the maximum data size, the
  489.  *    second gets the maximum parameter size.
  490.  *
  491.  * Side effects:
  492.  *    None.
  493.  *
  494.  *----------------------------------------------------------------------
  495.  */
  496. void
  497. Rpc_MaxSizes(maxDataSizePtr, maxParamSizePtr)
  498.     int *maxDataSizePtr;
  499.     int *maxParamSizePtr;
  500. {
  501.     if (maxDataSizePtr != (int *)NIL){
  502.     *maxDataSizePtr = RPC_MAX_DATASIZE;
  503.     }
  504.     if (maxParamSizePtr != (int *)NIL){
  505.     *maxParamSizePtr = RPC_MAX_PARAMSIZE;
  506.     }
  507. }
  508.